package smallfrench.moteur.biblio;

import smallfrench.moteur.biblio.err.ErreurParametres;
import smallfrench.moteur.interp.RObjet;

/**
 * Représente la classe d’un entier.
 * 
 * @author antoine1023
 *
 */
public class RClasseEntier extends RClasse {

	public static final RClasseEntier CLASSE = new RClasseEntier();

	private RClasseEntier() {
		super(new RClasse[] {RClasse.CLASSE});
		champs.put("abs", ABS);
		champs.put("enCaractere", EN_CARACTERE);
		champs.put("enChaine", EN_CHAINE);
		champs.put("enFlottant", EN_FLOTTANT);
	}

	@Override
	public REntier appeler(RObjet moi, RObjet[] params) {

		if (params.length == 0) {

			return new REntier(0l);

		} else if (params.length == 1) {

			RObjet param = params[0];

			if (param instanceof REntier) {
				return (REntier) param;

			} else if (param instanceof RFlottant) {
				RFlottant f = (RFlottant)param;
				return new REntier((long)f.valeur);

			} else if (param instanceof RChaine) {
				RChaine c = (RChaine)param;
				try {
					return new REntier(Long.parseLong(c.valeur));
				} catch (NumberFormatException e) {
					throw ErreurParametres.nouvelleException();
				}
			}
		}

		throw ErreurParametres.nouvelleException();
	}

	@Override
	public RChaine enChaine() {
		return new RChaine("Entier");
	}


	//------------------------------------------- Statics

	private static abstract class Fonction extends RFonction {

		public abstract RObjet appeler2(REntier moi, RObjet[] params);

		@Override
		public final RObjet appeler(RObjet moi, RObjet[] params) {
			if (moi instanceof REntier)
				return appeler2((REntier)moi, params);
			return null;
		}
	}

	/**
	 * Valeur absolue
	 */
	private final Fonction ABS = new Fonction() {
		@Override
		public RObjet appeler2(REntier moi, RObjet[] params) {
			return new REntier(Math.abs(moi.valeur));
		}
	};
	private final Fonction EN_FLOTTANT = new Fonction() {
		@Override
		public RObjet appeler2(REntier moi, RObjet[] params) {
			return new RFlottant(moi.valeur);
		}
	};
	private final Fonction EN_CARACTERE = new Fonction() {
		@Override
		public RObjet appeler2(REntier moi, RObjet[] params) {
			return new RChaine((char)moi.valeur);
		}
	};
	private final Fonction EN_CHAINE = new Fonction() {
		@Override
		public RObjet appeler2(REntier moi, RObjet[] params) {
			return new RChaine(moi.toString());
		}
	};
}
